package com.bolt.admin.security.shiro.realm;

import com.bolt.admin.exception.BizExceptionEnum;
import com.bolt.admin.security.shiro.AuthContextHolder;
import com.bolt.admin.security.shiro.AuthUserDetails;
import com.bolt.admin.security.shiro.DefaultAuthUserDetails;
import com.bolt.admin.security.shiro.PasswordUtil;
import com.bolt.admin.security.shiro.exception.AuthErrorException;
import com.bolt.admin.security.shiro.jwt.UserInfo;
import com.bolt.admin.module.sys.dto.converter.UserConverter;
import com.bolt.admin.module.sys.entity.UserEntity;
import com.bolt.admin.module.sys.service.UserService;
import com.bolt.common.utils.SpringContextUtil;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

/**
 * Created by Administrator on 2020/9/18.
 */
public class SessionPasswordRealm extends AuthorizingRealm {
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof UsernamePasswordToken;
    }

    /**
     * 认证回调函数,登录时调用.
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
        String username = token.getUsername();
        UserService userService = SpringContextUtil.getBean(UserService.class);
        UserEntity user  =  userService.findByUserName(username).orElseThrow(() ->
                new AuthErrorException(BizExceptionEnum.USER_NOT_EXISTED));
        //把盐值注入到用户输入密码，用于后续加密算法使用
        token.setPassword(PasswordUtil.injectPasswordSalt(
                String.valueOf(token.getPassword()), user.getAuthSalt()).toCharArray());
        DefaultAuthUserDetails authUser = new DefaultAuthUserDetails();
        authUser.setUserDTO(UserConverter.toDTO(user));
        authUser.setKey(String.valueOf(AuthContextHolder.getSessionId()));
        return new SimpleAuthenticationInfo(authUser, user.getPassword(), getName());
    }

    @Override
    public AuthorizationInfo getAuthorizationInfo(PrincipalCollection principals) {
        return super.getAuthorizationInfo(principals);
    }

    /**
     * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
     * 这里只需要认证登录，成功之后派发 json web token 授权在那里进
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        AuthUserDetails userDetails = AuthContextHolder.getAuthUserDetails();

        UserService userService = SpringContextUtil.getBean(UserService.class);
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        UserInfo userInfo = userService.userInfo(userDetails.getAccountId());
        info.setRoles(userInfo.getRoles());
        info.addStringPermissions(userInfo.getPermissions());

        return info;
    }
}

 